package cn.wolfcode.luowowo.interceptor;

import cn.wolfcode.luowowo.annotation.LoginAnnotation;
import cn.wolfcode.luowowo.cache.service.IUserInfoRedisService;
import cn.wolfcode.luowowo.domain.UserInfo;
import cn.wolfcode.luowowo.util.JsonResult;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 登录拦截器
 *  1. 检测用户是否登录
 */
public class CheckLoginInterceptor implements HandlerInterceptor{

    @Autowired
    private IUserInfoRedisService userInfoRedisService;

    /**
     * 拦截流程
     * @param request
     * @param response
     * @param handler
     * @return
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

        // 如果请求的方法不属于控制器的方法
        if(!(handler instanceof HandlerMethod)){
            // 放行 - 这里指的是静态资源以及,跨域请求的options请求
            return true;
        }
        /**
         * 1.
         * springmvc 启动的时候,会将所有的请求映射方法解析,并封装为一个对象:HeadlerMethod
         *           这个对象里面包含了请求映射方法的所有信息,包括映射方法上的注解
         *
         * 2.
         * springmvc 定义了一个类似map对象,管理所有请求映射方法对象
         *           map的key是请求映射方法的url路径, value是请求映射方法对象
         *           {
         *               "users/xxx"   handlermethod
         *               "users/yyy"   handlermethod
         *
         *           }
         *
         * 3.
         * 浏览器发起请求时,输入url地址 http:8080/users/xx
         * 服务器解析url地址获取 /user/xx ,从而拿到对应的 handlermethod
         *
         *
         * 4.springmvc 马上调用 CheckLoginInterceptor类对象,
         *   执行HandlerMethod 方法
         *   参数为
         *      1.请求对象
         *      2.响应对象
         *      3.handlerMethod对象
         *
         */



        // 如果请求的方式是控制器的方法
        /**
         * 下面2行代码的意思是,登录之后,访问任何页面都重置redis的过期时间
         * 放在判断里边会出现,只有访问需要登录的页面才会重置
         */
        // 1.获取带过来的token
        String token = request.getHeader("token");
        // 2.根据token获取用户信息
        UserInfo user = userInfoRedisService.getUserInfo(token);


        // 判断方法上是否贴有自定义注解
        HandlerMethod hm = (HandlerMethod) handler; // 强转,
        if (hm.hasMethodAnnotation(LoginAnnotation.class)) {
            // 3.如果获取到的user为空,要么过期了,要么没登录,都进行拦截
            if(user == null){
                // 设置响应信息字符集
                response.setContentType("application/json;charset=utf-8");
                // 添加响应信息给浏览器
                response.getWriter().write(JSON.toJSONString(JsonResult.noLogin()));
                return false;
            }
        }

        return true;
    }
}
